package org.springblade.modules.mes.opcua.itf.action;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedSubscription;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.springblade.modules.mes.opcua.config.OpcUaConfig;
import org.springblade.modules.mes.opcua.constant.OpcUaCache;
import org.springblade.modules.mes.opcua.constant.OpcUaUtil;
import org.springblade.modules.mes.opcua.itf.OpcUaItf;
import org.springblade.modules.mes.opcua.listener.OpcUaListener;
import org.springblade.modules.mes.opcua.listener.OpcUaSubscriptionListener;
import org.springblade.modules.mes.opcua.project.XsFilter;
import org.springblade.modules.mes.opcua.vo.OpcUaVO;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

@Component(value = "actOpcUa")
@Slf4j
public class ActOpcUa implements OpcUaItf {

	@Resource
	private OpcUaConfig opcConfig;

	@Resource
	private OpcUaListener prdDataValueListener;

	@Override
	public void init() {
		new Thread(() -> {
			try {
				OpcUaClient opcUaClient = OpcUaUtil.createClient(opcConfig.getEndPointUrl());
				opcUaClient.connect().get();
				Set<String> keys = new HashSet<>(OpcUaCache.getSubscriptionKeys());

				//添加监听
				final CountDownLatch eventLatch = new CountDownLatch(1);
				//处理订阅业务
				handlerNode(keys, opcUaClient);
				//添加订阅监听器，用于处理断线重连后的订阅问题
				opcUaClient.getSubscriptionManager().addSubscriptionListener(new OpcUaSubscriptionListener(keys, opcUaClient));
				//持续监听
				eventLatch.await();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}).start();
	}

	/**
	 * 处理订阅业务
	 *
	 * @param keys
	 */
	public void handlerNode(Set<String> keys, OpcUaClient client) {
		try {
			//创建订阅
			ManagedSubscription subscription = ManagedSubscription.create(client);
			List<NodeId> nodeIdList = new ArrayList<>();
			for (String key : keys) {
				log.info(key);
				nodeIdList.add(new NodeId(2, key));
			}
			//监听
			List<ManagedDataItem> dataItemList = subscription.createDataItems(nodeIdList);
			for (ManagedDataItem managedDataItem : dataItemList) {
				managedDataItem.addDataValueListener(prdDataValueListener);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	@Override
	public void writeValueShortFinal(OpcUaVO ctx, String position, String identifier, Object value) throws Exception {
		if(XsFilter.filter(identifier)) {
			OpcUaClient client = OpcUaUtil.getClient(opcConfig.getEndPointUrl());
			OpcUaUtil.writeValueShortFinal(ctx.opcuaKey(identifier, position), value, client);
		}
	}

	@Override
	public void writeValue(OpcUaVO ctx, String position, String identifier, Object value) throws Exception {
		if(XsFilter.filter(identifier)){
			OpcUaClient client = OpcUaUtil.getClient(opcConfig.getEndPointUrl());
			OpcUaUtil.writeValue(ctx.opcuaKey(identifier, position), value, client);
		}
	}


	@Override
	public Object readValue(String identifier) {
		OpcUaClient client = OpcUaUtil.getClient(opcConfig.getEndPointUrl());
		return OpcUaUtil.readValue(identifier, client);
	}



}
